package com.zbkj.crmeb.member.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.common.CommonPage;
import com.crmeb.core.common.CommonResult;
import com.common.PageParamRequest;
import com.crmeb.core.exception.CrmebException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zbkj.crmeb.enums.CouponUserTypeEnum;
import com.zbkj.crmeb.enums.WeekEnum;
import com.zbkj.crmeb.marketing.model.StoreCoupon;
import com.zbkj.crmeb.marketing.model.StoreCouponUser;
import com.zbkj.crmeb.marketing.service.StoreCouponService;
import com.zbkj.crmeb.marketing.service.StoreCouponUserService;
import com.zbkj.crmeb.member.dao.MerchantMemberBenefitsDao;
import com.zbkj.crmeb.member.enums.EquityTypeEnum;
import com.zbkj.crmeb.member.model.MerchantMemberBenefits;
import com.zbkj.crmeb.member.service.IMerchantMemberBenefitsService;
import com.zbkj.crmeb.member.vo.MerchantMemberBenefitsVO;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.model.UserMemberRecord;
import com.zbkj.crmeb.user.service.UserMemberRecordService;
import com.zbkj.crmeb.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 商户会员权益表 服务实现类
 * </p>
 *
 * @author xx
 * @since 2022-05-10
 */
@Service
public class MerchantMemberBenefitsServiceImpl extends ServiceImpl<MerchantMemberBenefitsDao, MerchantMemberBenefits> implements IMerchantMemberBenefitsService {

    @Autowired
    private StoreCouponService storeCouponService;
    @Autowired
    private UserMemberRecordService userMemberRecordService;
    @Autowired
    private UserService userService;
    @Autowired
    private StoreCouponUserService storeCouponUserService;
    @Override
    public CommonResult<String> addMemberBenefits(MerchantMemberBenefitsVO memberBenefitsVO) {
        MerchantMemberBenefits merchantMemberBenefits = this.getOne(Wrappers.lambdaQuery(MerchantMemberBenefits.class)
                .eq(MerchantMemberBenefits::getEquityType,memberBenefitsVO.getEquityType())
                .eq(MerchantMemberBenefits::getMerId,memberBenefitsVO.getMerId()));
        if (Objects.nonNull(merchantMemberBenefits)){
            return CommonResult.failed("该类型权益已存在");
        }
        if (Objects.equals(EquityTypeEnum.COUPON.getCode(),memberBenefitsVO.getEquityType()) && memberBenefitsVO.getEquityEnableFlag()){
            if (StringUtils.isBlank(memberBenefitsVO.getAssociatedCouponId())){
                return CommonResult.failed("优惠券权益开启时需要添加会员优惠券");
            }
        }
        merchantMemberBenefits = new MerchantMemberBenefits();
        BeanUtil.copyProperties(memberBenefitsVO,merchantMemberBenefits);
        merchantMemberBenefits.setCreateTime(new Date());
        return this.save(merchantMemberBenefits) ? CommonResult.success() : CommonResult.failed();
    }

    @Override
    public CommonPage<MerchantMemberBenefits> getMemberBenefits(Integer merId, PageParamRequest pageParamRequest) {
        Page<MerchantMemberBenefits> page = PageHelper.startPage(pageParamRequest.getPage(),pageParamRequest.getLimit());
        List<MerchantMemberBenefits> memberBenefitsList = this.list(Wrappers.lambdaQuery(MerchantMemberBenefits.class)
                .eq(MerchantMemberBenefits::getMerId,merId));
        return CommonPage.restPage(CommonPage.copyPageInfo(page, memberBenefitsList));
    }

    @Override
    public Boolean updMemberBenefits(MerchantMemberBenefitsVO memberBenefitsVO) {
        MerchantMemberBenefits merchantMemberBenefits = this.getById(memberBenefitsVO.getId());
        if (Objects.isNull(merchantMemberBenefits)){
            throw new CrmebException("请检查当前权益是否存在");
        }
        int count = this.count(Wrappers.lambdaQuery(MerchantMemberBenefits.class)
                .eq(MerchantMemberBenefits::getEquityType,merchantMemberBenefits.getEquityType())
                .eq(MerchantMemberBenefits::getMerId,memberBenefitsVO.getMerId())
                .ne(MerchantMemberBenefits::getId,memberBenefitsVO.getId()));
        if (count > 0){
            throw new CrmebException("该类型权益已存在");
        }
        if (Objects.equals(EquityTypeEnum.COUPON.getCode(),merchantMemberBenefits.getEquityType()) && memberBenefitsVO.getEquityEnableFlag()){
            if (StringUtils.isBlank(memberBenefitsVO.getAssociatedCouponId())){
                throw new CrmebException("优惠券权益开启时需要添加会员优惠券");
            }
        }
        BeanUtil.copyProperties(memberBenefitsVO,merchantMemberBenefits);
        return this.updateById(merchantMemberBenefits);
    }

    @Override
    public Boolean delMemberBenefits(Integer id) {
        return this.removeById(id);
    }

    @Override
    public void distributeCouponsRegularly() {
        Integer lock = 0;
        synchronized (lock){
            //查询所有已开启优惠券的商户
            List<MerchantMemberBenefits> memberBenefitsList = this.list(Wrappers.lambdaQuery(MerchantMemberBenefits.class)
                    .eq(MerchantMemberBenefits::getEquityType,EquityTypeEnum.COUPON.getCode())
                    .eq(MerchantMemberBenefits::getEquityEnableFlag,true));
            if (CollectionUtils.isEmpty(memberBenefitsList)){
                return;
            }
            List<Integer> merIdList = memberBenefitsList.stream().map(MerchantMemberBenefits::getMerId).collect(Collectors.toList());

            //查询商户当前日期是否有设置自动发放的优惠券
            List<StoreCoupon> storeCouponList = storeCouponService.list(Wrappers.lambdaQuery(StoreCoupon.class)
                    .eq(StoreCoupon::getType,3)
                    .eq(StoreCoupon::getCrowd,4)
                    .eq(StoreCoupon::getIsDel,false)
                    .eq(StoreCoupon::getStatus, false)
                    // 按月发放优惠券
                    .and(qr -> qr.eq(StoreCoupon::getReleaseType,2)
                            .eq(StoreCoupon::getReleaseDate, DateUtil.dayOfMonth(new Date()))
                            // 按周发放优惠券
                            .or()
                            .eq(StoreCoupon::getReleaseType, 3)
                            .eq(StoreCoupon::getReleaseDate, WeekEnum.getWeekDayByCode(String.valueOf(LocalDate.now().getDayOfWeek()))))
                    .in(StoreCoupon::getMerId,merIdList));
            if (CollectionUtils.isEmpty(storeCouponList)){
                return;
            }
            merIdList = storeCouponList.stream().map(StoreCoupon::getMerId).collect(Collectors.toList());

            //查看当月是否有用户已领取优惠券，避免多次发放
            List<Integer> couponList = storeCouponList.stream().map(StoreCoupon::getId).collect(Collectors.toList());
            List<StoreCouponUser> receivedList = storeCouponUserService.list(Wrappers.lambdaQuery(StoreCouponUser.class)
                    .in(StoreCouponUser::getCouponId,couponList)
                    .apply("DATE_FORMAT( create_time, '%Y%m' ) = DATE_FORMAT( now(), '%Y%m' ) "));

            //获取商户已开启会员用户
            List<UserMemberRecord> userMemberRecordList = userMemberRecordService.list(Wrappers.lambdaQuery(UserMemberRecord.class)
                    .eq(UserMemberRecord::getPaid,true)
                    .gt(UserMemberRecord::getExpirationTime,new Date())
                    .in(UserMemberRecord::getMerId,merIdList));
            if (CollectionUtils.isEmpty(userMemberRecordList)){
                return;
            }
            List<Integer> uidList = userMemberRecordList.stream().map(UserMemberRecord::getUid).collect(Collectors.toList());
            List<User> userList = userService.list(Wrappers.lambdaQuery(User.class).eq(User::getStatus,true).in(User::getUid,uidList));
            if (CollectionUtils.isEmpty(userList)){
                return;
            }

            List<StoreCouponUser> storeCouponUserList = new ArrayList<>();
            storeCouponList.forEach(storeCoupon -> userList.forEach(user -> {
                if (receivedList.stream().anyMatch(storeCouponUser -> Objects.equals(storeCouponUser.getUid(),user.getUid()) && Objects.equals(storeCouponUser.getCouponId(),storeCoupon.getId()))){
                    return;
                }
                if (Objects.equals(storeCoupon.getMerId(),user.getMerId())){
                    StoreCouponUser storeCouponUser = new StoreCouponUser();
                    storeCouponUser.setMerId(storeCoupon.getMerId());
                    storeCouponUser.setCouponId(storeCoupon.getId());
                    storeCouponUser.setUid(user.getUid());
                    storeCouponUser.setUserNick(user.getNickname());
                    storeCouponUser.setUserPhone(user.getPhone());
                    storeCouponUser.setName(storeCoupon.getName());
                    storeCouponUser.setMoney(storeCoupon.getMoney());
                    storeCouponUser.setUseType(storeCoupon.getUseType());
                    storeCouponUser.setPrimaryKey(storeCoupon.getPrimaryKey());
                    storeCouponUser.setMinPrice(storeCoupon.getMinPrice());
                    storeCouponUser.setType(CouponUserTypeEnum.AUTO.getCode());
                    storeCouponUser.setStatus(0);
                    storeCouponUser.setCreateTime(new Date());
                    // 固定时间
                    if (storeCoupon.getIsFixedTime()) {
                        storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
                        storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
                        // 有效天数
                    } else {
                        LocalDateTime time = LocalDateTime.now();
                        LocalDateTime startTime = time.plusDays(storeCoupon.getLastDay());
                        LocalDateTime endTime = startTime.plusDays(storeCoupon.getDay());

                        ZoneId zoneId = ZoneId.systemDefault();
                        Date startDate = Date.from(startTime.atZone(zoneId).toInstant());
                        Date endDate = Date.from(endTime.atZone(zoneId).toInstant());

                        storeCouponUser.setStartTime(startDate);
                        storeCouponUser.setEndTime(endDate);
                    }
                    storeCouponUserList.add(storeCouponUser);
                }
            }));
            storeCouponUserService.saveBatch(storeCouponUserList);
        }
    }

    @Override
    public void automaticallyIssueCoupons(Integer uid) {
        User user = userService.getById(uid);
        MerchantMemberBenefits merchantMemberBenefits = this.getOne(Wrappers.lambdaQuery(MerchantMemberBenefits.class)
                .eq(MerchantMemberBenefits::getEquityType,EquityTypeEnum.COUPON.getCode())
                .eq(MerchantMemberBenefits::getEquityEnableFlag,true)
                .eq(MerchantMemberBenefits::getMerId,user.getMerId()));
        if (Objects.isNull(merchantMemberBenefits)){
            return;
        }
        List<Integer> integerList = Convert.toList(Integer.class,merchantMemberBenefits.getAssociatedCouponId().split(","));
        //查询是否有立即到账优惠券
        List<StoreCoupon> storeCouponList = storeCouponService.list(Wrappers.lambdaQuery(StoreCoupon.class)
                .eq(StoreCoupon::getType,4)
                .eq(StoreCoupon::getCrowd,4)
                .eq(StoreCoupon::getIsDel,false)
                .eq(StoreCoupon::getMerId,user.getMerId())
                .in(StoreCoupon::getId,integerList));
        if (CollectionUtils.isEmpty(storeCouponList)){
            return;
        }
        List<Integer> couId = storeCouponList.stream().map(StoreCoupon::getId).collect(Collectors.toList());
        List<StoreCouponUser> receivedList = storeCouponUserService.list(Wrappers.lambdaQuery(StoreCouponUser.class)
                .in(StoreCouponUser::getCouponId,couId).eq(StoreCouponUser::getUid,user.getUid()));
        List<Integer> couponUser = receivedList.stream().map(StoreCouponUser::getCouponId).collect(Collectors.toList());
        List<StoreCouponUser> storeCouponUserList = new ArrayList<>();
        storeCouponList.forEach(storeCoupon -> {
            if (!couponUser.contains(storeCoupon.getId())){
                StoreCouponUser storeCouponUser = new StoreCouponUser();
                storeCouponUser.setMerId(storeCoupon.getMerId());
                storeCouponUser.setCouponId(storeCoupon.getId());
                storeCouponUser.setUid(user.getUid());
                storeCouponUser.setUserNick(user.getNickname());
                storeCouponUser.setUserPhone(user.getPhone());
                storeCouponUser.setName(storeCoupon.getName());
                storeCouponUser.setMoney(storeCoupon.getMoney());
                storeCouponUser.setUseType(storeCoupon.getUseType());
                storeCouponUser.setPrimaryKey(storeCoupon.getPrimaryKey());
                storeCouponUser.setMinPrice(storeCoupon.getMinPrice());
                storeCouponUser.setType(CouponUserTypeEnum.AUTO.getCode());
                storeCouponUser.setStatus(0);
                storeCouponUser.setCreateTime(new Date());
                // 固定时间
                if (storeCoupon.getIsFixedTime()) {
                    storeCouponUser.setStartTime(storeCoupon.getUseStartTime());
                    storeCouponUser.setEndTime(storeCoupon.getUseEndTime());
                    // 有效天数
                } else {
                    LocalDateTime time = LocalDateTime.now();
                    LocalDateTime startTime = time.plusDays(storeCoupon.getLastDay());
                    LocalDateTime endTime = startTime.plusDays(storeCoupon.getDay());

                    ZoneId zoneId = ZoneId.systemDefault();
                    Date startDate = Date.from(startTime.atZone(zoneId).toInstant());
                    Date endDate = Date.from(endTime.atZone(zoneId).toInstant());

                    storeCouponUser.setStartTime(startDate);
                    storeCouponUser.setEndTime(endDate);
                }
                storeCouponUserList.add(storeCouponUser);
            }
        });
        if (CollectionUtils.isNotEmpty(storeCouponList)){
            storeCouponUserService.saveBatch(storeCouponUserList);
        }
    }
}
